/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.gitee.fdc.base.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.gitee.fdc.base.dao.BaseTreeDao;
import com.gitee.fdc.base.entity.TreeEntity;
import com.gitee.fdc.web.ztree.ZTreeNode;
import java.io.Serializable;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

/**
 *
 * @author qskj
 * @param <T>
 */
public class BaseTreeServiceImpl<T extends TreeEntity, ID extends Serializable> extends BaseServiceImple<T,ID> implements BaseTreeService<T,ID> {

    BaseTreeDao dao;

    private void setDao(BaseTreeDao dao) {
        this.dao = dao;
    }

    public void init(Class entityClass, BaseTreeDao dao) {
        this.dao = dao;
        super.init(entityClass, dao);
    }

    @Override
    public T findById(ID id) {
        return (T) this.dao.findById(id);
    }

    @Transactional(readOnly = false)
    public int save(T entity) {
        int rt;
        String oldParentIds = "";
        String newParentIds = "";

        T oldObj = null;
        if (entity.getId() != null) {
            oldObj = (T) dao.selectByPrimaryKey(entity.getId());
            oldParentIds = oldObj.getPids() + oldObj.getId() + ",";
        }

        // 如果没有设置父节点，则代表为跟节点，有则获取父节点实体
        if (entity.getParent() == null && (entity.getPid() == null || entity.getPid() == 0)) {
            entity.setParent(null);
            entity.setPid(null);
            entity.setPids("0,");
            newParentIds = entity.getPids();
        } else {

            T parent = (T) dao.selectByPrimaryKey(entity.getPid());
            String pids = parent.getPids() + entity.getPid() + ",";
            entity.setPids(pids);
            newParentIds = pids + entity.getId() + ",";;
        }

        // 保存或更新实体
        rt = super.save(entity);
        if (oldObj != null && !oldParentIds.endsWith(newParentIds)) {
            // 更新子节点 parentIds
            if (!newParentIds.equalsIgnoreCase(oldParentIds) && newParentIds.startsWith(oldParentIds)) {
                throw new RuntimeException("这么设置父级不合适吧，再想想！");
            }
            dao.batchReplacePidsPath(oldParentIds, newParentIds);
        }
        return rt;
    }

    public List<T> findByParentIdIncludeParent(ID pid) {
        if (pid != null && pid != TreeEntity.DUMMY_ROOT_ID) {
            TreeEntity p = this.dao.findById(pid);
            String pidsLike = p.getPids() + p.getId() + ",%";

            Example exp = new Example(this.getEntityClass());
            exp.createCriteria().andEqualTo("id", pid).orLike("pids", pidsLike);
            return this.dao.selectByExample(exp);
        } else {
            Example exp = new Example(this.getEntityClass());
            exp.createCriteria().orLike("pids", TreeEntity.ROOT_PID_LIKE);
            return this.dao.selectByExample(exp);

        }
    }

    public List<T> findByParentIdExcludeParent(ID pid) {
        if (pid != null && pid != TreeEntity.DUMMY_ROOT_ID) {
            TreeEntity p = this.dao.findById(pid);
            String pidsLike = p.getPids() + p.getId() + ",%";

            Example exp = new Example(this.getEntityClass());
            exp.createCriteria().andLike("pids", pidsLike);
            return this.dao.selectByExample(exp);
        } else {
            Example exp = new Example(this.getEntityClass());
            exp.createCriteria().andLike("pids", TreeEntity.ROOT_PID_LIKE);
            return this.dao.selectByExample(exp);

        }
    }

    @Override
    public List<ZTreeNode> presetTreeDataChecked(List<T> source, List<T> checked) {
        return this.convertToZTreeNode(source, convertCheckedListToMap(checked));
    }

    private Map<Integer, T> convertCheckedListToMap(List<T> checked) {
        Map m = new HashMap();
        for (T t : checked) {
            m.put(t.getId(), t);
        }
        return m;
    }

    public List<ZTreeNode> convertToZTreeNode(List<T> dl, Map<Integer, T> chencked) {
        List<ZTreeNode> l = new ArrayList();
        for (Iterator<T> iterator = dl.iterator(); iterator.hasNext();) {
            T n = iterator.next();
            ZTreeNode one = convertToZTreeNode(n, chencked);
            l.add(one);
        }
        return l;
    }

    private ZTreeNode convertToZTreeNode(T n, Map<Integer, T> chencked) {
        ZTreeNode one = new ZTreeNode();
        one.setId(n.getId());
        if (n.getPid() != null) {
            one.setpId(n.getPid());
        }
        one.setName(n.getDisplayName());
        one.setChecked(chencked.containsKey(one.getId()));
        return one;
    }

    @Override
    public List<ZTreeNode> convertTreeNodes(List<T> source) {
        return this.convertToZTreeNode(source, new HashMap());
    }

//    @Override
//    public List<T> findByParentIdIncludeParent(ID pid) {
//        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
//    }
}
